#if !defined(_SHELL_H)
#define _SHELL_H

#include <iostream>
#include <fstream>
#include <queue>

#if !defined(WIN32)
   #include <readline/readline.h>
   #include <readline/history.h>
#endif

#include <scott/Plugin.h>
#include <scott/Scott.h>
#include <scott/Utility.h>
#include <scott/SEnumTypeDescriptor.h>
#include <scott/INameResolutor.h>
#include <scott/ExpressionResolutor.h>

#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#include <boost/foreach.hpp>

#include <boost/filesystem.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>

using namespace boost::filesystem;

#define DECLARATION_DLL

CREATE_ALIAS( Shell )

#if defined(WIN32)
  #define SCOTT_CONFIGURATION_FILE "scott.ini"
#else
  #define SCOTT_CONFIGURATION_FILE "./etc/scottrc"
#endif

/**
 * The shell class.
 */
class Shell
{
	/**
	 * Reference to the SCOTT core library API.
	 */
	ScottSp scott;

	/**
	 * Reference of the descriptors repository.
	 */
	DescriptorsRepositorySp descriptorsRepository;

	/**
	 * Reference to a name resolutor.
	 */
	INameResolutorSp nameResolutor;

	/**
	 * Map used to store all loaded plugins.
	 */
	PluginSpMapSp plugins;

	/**
	 * Shell variables.
	 */
	SValueSpMapSp vars;

	/**
	 * Object used for regular expression.
	 */
	smatch m;

	/**
	 * Shell commands.
	 */
	queue<string> inputLines;

	/**
	 * The stream where the fwrite shell command write.
	 * You can set this stream with the shell command 'fopen'.
	 */
	ofstream exportFileStream;

	/**
	 * Returns true if there is a current plugin selected.
	 */
	bool IsPluginLoaded();

	/**
	 * Execute a shell command.
	 */
	void ExecuteShellCommand(string command, string input);

	/**
	 * Returns true if a command is a shell command.
	 */
	bool IsShellCommand(string command);

	/**
	 * Print the syntax of a shell command.
	 */
	void ShowShellCommandSyntax(string command);

	/**
	 * Check if input is a plugin command invocation.
	 * If yes the command is executed and returns true
	 * otherwise returns false.
	 */
	bool ExecutePluginCommand( string input );

	/**
	 * Read a line of text from input.
	 */
	string ReadLine();

	/**
	 * Read the file stream and return all as a string.
	 */
	string ReadAllFile( ifstream &file) ;

	/************************************************/
	/*       Scott Shell settings                   */
	/************************************************/

	/** True if the automatic variable mechanism is enabled. */
	bool autovars;

	/** True if the implicit variable mechanism is enabled. */
	bool implicitvars;

	/** True if the dump variables mechanism is enabled. */
	bool dumpvars;

	/************************************************/
	/*        Scott Shell command handlers          */
	/************************************************/

	/** Handler of "help" shell command. */
	virtual void Help();

	/** Handler of detailed "help" shell command. */
	virtual void Help(string name);

	/** Handler of "plugins" shell command. */
	virtual void Plugins();

	/** Handler of "load" shell command. */
	virtual void Load(string pluginName);

	/** Handler of "commands" shell command. */
	virtual void Commands();

	/** Handler of "tyoes" shell command. */
	virtual void Types();

	/** Handler of "vars" shell command. */
	virtual void Vars();

	/** Handler of "show" shell command. */
	virtual void Show(string varName);

	/** Handler of "var" shell command. */
	virtual void Var(string type, string varName, string expression);

	/** Handler of "autovars" shell command. */
	virtual void Autovars(string val);

	/** Handler of "implicitvars" shell command. */
	virtual void Implicitvars(string val);

	/** Handler of "dumpvars" shell command. */
	virtual void Dumpvars(string val);

	/** Handler of "write" and "writeln" shell commands. */
	virtual void Write(string format, string varList, bool endLine);

	/** Handler of "fopen" shell command. */
	virtual void FOpen(string fileName);

	/** Handler of "fwrite" and "fwriteln" shell commands. */
	virtual void FWrite(string format, string varList, bool endLine);

	/** Handler of "fclose" shell command. */
	virtual void FClose();

	/** Handler of "settings" shell command. */
	virtual void Settings();

	/** Create the shell. */
	Shell(INameResolutorSp nameResolutor);

	public:

		/**
		 * Factory method to create the shell with a specif name resolutor.
		 */
		static ShellSp Create(INameResolutorSp nameResolutor);

		/**
		 * Start the shell.
		 */
		virtual void Start();
};

#endif // _SHELL_H
